/*
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  
 */

using System;
using java = biz.ritter.javapi;
using org.apache.commons.collections;

namespace org.apache.commons.collections.collection
{

    /**
     * Decorates another <code>Collection</code> to transform objects that are added.
     * <p>
     * The add methods are affected by this class.
     * Thus objects must be removed or searched for using their transformed form.
     * For example, if the transformation converts Strings to Integers, you must
     * use the Integer form to remove objects.
     * <p>
     * This class is java.io.Serializable from Commons Collections 3.1.
     *
     * @since Commons Collections 3.0
     * @version $Revision: 7263 $ $Date: 2011-06-12 13:28:27 +0200 (So, 12. Jun 2011) $
     * 
     * @author Stephen Colebourne
     */
    [Serializable]
    public class TransformedCollection : AbstractSerializableCollectionDecorator
    {

        /** Serialization version */
        private static readonly long serialVersionUID = 8692300188161871514L;

        /** The transformer to use */
        protected readonly Transformer transformer;

        /**
         * Factory method to create a transforming collection.
         * <p>
         * If there are any elements already in the collection being decorated, they
         * are NOT transformed.
         * 
         * @param coll  the collection to decorate, must not be null
         * @param transformer  the transformer to use for conversion, must not be null
         * @return a new transformed collection
         * @throws IllegalArgumentException if collection or transformer is null
         */
        public static java.util.Collection<Object> decorate(java.util.Collection<Object> coll, Transformer transformer)
        {
            return new TransformedCollection(coll, transformer);
        }

        //-----------------------------------------------------------------------
        /**
         * Constructor that wraps (not copies).
         * <p>
         * If there are any elements already in the collection being decorated, they
         * are NOT transformed.
         * 
         * @param coll  the collection to decorate, must not be null
         * @param transformer  the transformer to use for conversion, must not be null
         * @throws IllegalArgumentException if collection or transformer is null
         */
        protected TransformedCollection(java.util.Collection<Object> coll, Transformer transformer)
            : base(coll)
        {
            if (transformer == null)
            {
                throw new java.lang.IllegalArgumentException("Transformer must not be null");
            }
            this.transformer = transformer;
        }

        /**
         * Transforms an object.
         * <p>
         * The transformer itself may throw an exception if necessary.
         * 
         * @param object  the object to transform
         * @return a transformed object
         */
        protected internal virtual Object transform(Object obj)
        {
            return transformer.transform(obj);
        }

        /**
         * Transforms a collection.
         * <p>
         * The transformer itself may throw an exception if necessary.
         * 
         * @param coll  the collection to transform
         * @return a transformed object
         */
        protected virtual java.util.Collection<Object> transform(java.util.Collection<Object> coll)
        {
            java.util.List<Object> list = new java.util.ArrayList<Object>(coll.size());
            for (java.util.Iterator<Object> it = coll.iterator(); it.hasNext(); )
            {
                list.add(transform(it.next()));
            }
            return list;
        }

        //-----------------------------------------------------------------------
        public override bool add(Object obj)
        {
            obj = transform(obj);
            return getCollection().add(obj);
        }

        public override bool addAll(java.util.Collection<Object> coll)
        {
            coll = transform(coll);
            return getCollection().addAll(coll);
        }
    }
}